//
//  PLISTDictionary_to_Settings.cpp
//  sad
//
//  Created by Christopher Kemsley on 2/4/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//



#include "Codec.hpp"
#include "PLISTParser.hpp"
#include "URL.hpp"
#include "Settings.hpp"

#include "Log.hpp"
#include "Exception.hpp"

using namespace Sim ;


// This is a combinatorial type. Converts
// URL -> PLIST -> Settings
struct URL_to_Settings : public aCodec < Settings* , URL* >
{
	URL_to_Settings ()
	:	aCodec<Settings*,URL*> ()
	{ }
	
	
	virtual bool	runDecode		( Any const & anyView , Any const & anyModel )
		{
		PLISTParser::Dictionary		info ;
		
		
		try {
			if ( Codec :: decode ( anyView , info ) )
				return Codec :: decode ( info , anyModel ) ;
		} catch ( Exception & e ) {
			Log :: logException ( e ) ;
			AddExceptionTrace ( e , "PLISTDictionary_to_Settings" , "Codec failed with "<< *(anyView.as<URL*>()) , __FILE__,__LINE__ ) ;
			throw e ;
		}
		
		return false ;
		}
	
} ;
URL_to_Settings _URL_to_Settings ;






struct PLISTDictionary_to_Settings : public aCodec < Settings* , PLISTParser::Dictionary* >
{
	PLISTDictionary_to_Settings ()
	:	aCodec<Settings*,PLISTParser::Dictionary*> ()
	{ }
	
	
	virtual bool	runDecode		( Any const & anyView , Any const & anyModel )
		{
		Settings&						settings=	* anyModel.as<Settings*>() ;
		
		// find OUR section
		PLISTParser::Dictionary const&	allInfo	=	* anyView.as<PLISTParser::Dictionary*>() ;
		PLISTParser::Dictionary::const_iterator	_found	=	allInfo . find ( settings.instanceName() ) ;
		
		Log::states("PLISTDictionary_to_Settings") << "Decoding settings instance " << settings.instanceName() ;
		
		if ( _found == allInfo.end() )
			ThrowException ( "Codec::PLISTDictionary_to_Settings" , "Failed to find info for \""<<settings.instanceName()<<"\"" , __FILE__,__LINE__ ) ;
		
		
		Any	const & _value	=	(*_found).second ;
		PLISTParser::Dictionary const&	info	=	_value.as<PLISTParser::Dictionary>() ;
		
		if ( info.size() == 0 )
			{
			Log::notice("PLISTDictionary_to_Settings") << "Failed to decode PLIST to settings (plist size is zero)" ;
			return true ;
			}
		
		
		Settings::Variables::const_iterator	here	=	settings.variables().begin() ;
		Settings::Variables::const_iterator	end		=	settings.variables().end() ;
		
		PLISTParser::Dictionary::const_iterator	iEnd	=	info.end() ;
		
		
		while ( here != end )
			{
			std::string const&	name	=	(*here) . first ;
			Any const&			ptr		=	(*here) . second ;
			here ++ ;
			
			Log::states("PLISTDictionary_to_Settings") << "...decoding " << name ;
			
			// Find the value
			PLISTParser::Dictionary::const_iterator	iValue	=	info.find(name) ;
			
			if ( iValue != iEnd ) // then we have a value for it
				{
				if ( ! Codec::decodeAny( (*iValue).second , ptr ) )
					{
					Log::error("PLISTDictionary_to_Settings") << "Failed to decode \"" << name << "\" (decoder failed)\n" ;
					}
				}
			else
				{
				Log::notice("PLISTDictionary_to_Settings") << "Failed to decode \"" << name << "\" (plist has no value)" ;
				}
			}
		
		
		try {
			settings . validate() ;
		} catch ( Exception & e ) {
			Log :: logException ( e ) ;
			AddExceptionTrace ( e , "PLISTDictionary_to_Settings" , "Validation failed of "<<settings.instanceName() , __FILE__,__LINE__ ) ;
			throw e ;
		}
		return true ;
		}
	
} ;
PLISTDictionary_to_Settings _PLISTDictionary_to_Settings ;
